﻿using System;
using System.Linq;
using System.Linq.Expressions;
using Sharp.Domain.Model;
using Sharp.Infrastructure;
using Sharp.Infrastructure.IoC;
using Sharp.Infrastructure.Model;

namespace Sharp.Domain.Repository.EF
{
    /// <summary>
    /// 仓储过滤器
    /// </summary>
    internal static class RepositoryFilter
    {
        /// <summary>
        /// 过滤saas的数据
        /// </summary>
        /// <param name="query"></param>
        /// <returns></returns>
        internal static IQueryable<TAggregateRoot> FilterSassData<TKey, TAggregateRoot>(this IQueryable<TAggregateRoot> query)
            where TAggregateRoot : class, IAggregateRoot<TKey>
            where TKey : struct
        {
            var left = Expression.Parameter(typeof(TAggregateRoot), "m");

            if (ServiceLocator.Instance.IsRegistered<IDataPermission>()
                &&
                typeof(TAggregateRoot).GetInterface(nameof(ILogCreatedEntity)) != null)
            {
                var userIds = ServiceLocator.Instance.GetService<IDataPermission>().GetDataPermissionForUser(typeof(TAggregateRoot));

                if (userIds != null)
                {
                    Expression expression = Expression.Constant(false);
                    foreach (var userid in userIds)
                    {
                        Expression constant = Expression.Constant(userid);
                        var t = Expression.Property(left, nameof(ILogCreatedEntity.CreatedUserId)).Type;
                        var m = t.GetMethod(t == typeof(Guid?) ? "op_Equality" : "Equal");

                        Expression right = Expression.Equal(Expression.Property(left, nameof(ILogCreatedEntity.CreatedUserId)),
                            Expression.Convert(constant, t), false, m);

                        expression = Expression.Or(right, expression);
                    }
                    query = query.Where(Expression.Lambda<Func<TAggregateRoot, bool>>(expression, left));
                }
            }

            #region 额外组织权限
            if (!typeof(IFilter4Org).IsAssignableFrom(typeof(TAggregateRoot)))
                return query;
            if (!ServiceLocator.Instance.IsRegistered<IDataPermission>())
            {
                return query;
            }
            var orgids = ServiceLocator.Instance.GetService<IDataPermission>().GetDataPermissionForDev(typeof(TAggregateRoot)).ToList();

            if (orgids.Any())
            {
                Expression expression = Expression.Constant(false);
                foreach (var orgid in orgids)
                {
                    Expression constant = Expression.Constant(orgid);
                    var t = Expression.Property(left, nameof(IFilter4Org.OrgId)).Type;
                    var m = t.GetMethod(t == typeof(Guid?) ? "op_Equality" : "Equal");

                    Expression right = Expression.Equal(Expression.Property(left, nameof(IFilter4Org.OrgId)),
                        Expression.Convert(constant, t), false, m);

                    expression = Expression.Or(right, expression);
                }
                query = query.Where(Expression.Lambda<Func<TAggregateRoot, bool>>(expression, left));
            }

            #endregion

            return query;
        }
    }
}